//********************************************************************************************************
// Product Name: MapWindow.dll Alpha
// Description:  The basic module for MapWindow version 6.0
//********************************************************************************************************
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); 
// you may not use this file except in compliance with the License. You may obtain a copy of the License at 
// http://www.mozilla.org/MPL/ 
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 
// ANY KIND, either expressed or implied. See the License for the specificlanguage governing rights and 
// limitations under the License. 
//
// The Original Code is from MapWindow.dll version 6.0
//
// The Initial Developer of this Original Code is Ted Dunsford. Created 3/8/2008 7:19:53 AM
// 
// Contributor(s): (Open source contributors should list themselves and their modifications here). 
//
//********************************************************************************************************

using System;
using System.Collections.Generic;
using System.ComponentModel;
using MapWindow.DirectX.Data;
using MapWindow.Drawing;
using MapWindow.Geometries;
using MapWindow.Main;
using Microsoft.DirectX;

namespace MapWindow.DirectX
{


    /// <summary>
    /// Texture
    /// </summary>
    public class ModelLayerDX: LayerDX, IModelLayerDX
    {
       


        #region Private Variables

        // TO DO: xml to store the locations etc.
        // private string _filename;
        // Each layer gets a single model to draw, but that model can be drawn in many locations
        private ModelDX _model;
        private List<Vector3> _locations;
        private ModelSymbolizer _symbolizer;

       

       

        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new instance of a mesh layer
        /// </summary>
        public ModelLayerDX()
        {
            Configure();
           
           
        }

       
        /// <summary>
        /// Creates the layer with a default position and location, but also 
        /// </summary>
        /// <param name="model">The ModelDX that should be drawn in various places for this layer.</param>
        public ModelLayerDX(ModelDX model)
        {
            Model = model;
            Configure();
        }

        private void Configure()
        {
            _symbolizer = new ModelSymbolizer();
            _locations = new List<Vector3>();
            _locations.Add(new Vector3(0, 0, 0));


            //_filename = "NotSupportedYet";
            if (_model != null)
            {

                LegendText = System.IO.Path.GetDirectoryName(_model.Filename);
            }
            else
            {
                LegendText = "Empty";
            }
            IsVisible = true;
          
            
          

        }

        void _bounds_BoundsChanged(object sender, EventArgs e)
        {
            IsInitialized = false;
          
        }

       
        #endregion

        #region Methods

      


        /// <summary>
        /// This is the internal drawing method that follows the standard checks.  Drawing is evoked
        /// through the Draw3D command, but internally implemented in the DrawPart method.  After
        /// the initial checks, the Draw3D method will cycle the part integer from 0 to NumParts -1.
        /// </summary>
        /// <param name="args">A DrawArgsDX class with the device and camera.</param>
        protected override void OnDraw(DrawArgsDX args)
        {
           
           
            if (_locations == null) return;

            Matrix mat = Matrix.Identity;
            if (_symbolizer.ScaleMode == ScaleModes.Symbolic)
            {
                mat = Matrix.Scaling(Math.Abs(args.Camera.CameraPosition.Z) / 100, Math.Abs(args.Camera.CameraPosition.Z) / 100, Math.Abs(args.Camera.CameraPosition.Z) / 100);
            }
            mat = Matrix.Multiply(mat, _symbolizer.GetMatrix());
            args.Device.Transform.World = mat;
            
            foreach (Vector3 location in _locations)
            {
                
                _model.Draw3D(args);
            }

            args.Device.Transform.World = Matrix.Identity;

            
          
            

        }



        

        // This sets up the texture if it hasn't been set up yet.
        /// <summary>
        /// Initialize
        /// </summary>
        public override void Initialize(DrawArgsDX args)
        {
            if (_locations == null)
            {
                _locations = new List<Vector3>();
                _locations.Add(new Vector3(0,0,0));
            }
            _model.Initialize(args);
            base.Initialize(args);

        }



       
       
        
       
        /// <summary>
        /// This layer doesn't actually support changing the image.  Instead, this simply updates the worldfile,
        /// but only if the style is georeferenced.
        /// </summary>
        public virtual void Save()
        {
            _model.Save();

            // TO DO: Positions / transforms
        }

        #endregion

        #region Properties

        

        /// <summary>
        /// Obtains an envelope that contains this image
        /// </summary>
        /// <returns>An IEnvelope</returns>
        [Category("Bounds"), Description("Gets an envelope containing this."),
        TypeConverter(typeof(ExpandableObjectConverter))] 
        public override IEnvelope Envelope
        {
            get
            {
                return _model.Envelope;
            }
        }

        /// <summary>
        /// Gets or sets the list of models that will be drawn by this layer
        /// </summary>
        public ModelDX Model
        {
            get
            {
                return _model;
            }
            set
            {
                _model = value;
                _model.Inititialized += new EventHandler<DrawArgsDX>(_model_Inititialized);
            }
        }

        void _model_Inititialized(object sender, DrawArgsDX e)
        {
            OnVisibleChanged(sender, e);
        }



        /// <summary>
        /// Gets or sets the symbolizer to use for the models on this layer
        /// </summary>
        public ModelSymbolizer Symbolizer
        {
            get { return _symbolizer; }
            set { _symbolizer = value; }
        }
 

    

      

        #endregion


       








        

     
    }

}
